#include "MixPool.h"
#include "CrypUtil.h"
#include "StrUtil.h"

namespace x2lib
{
    MixPool::MixPool(const char* pszPwd)
    {
        strcpy(m_szPwd, pszPwd);
    }

    MixPool::MixPool(const char* pszPwd, const char* szKey, void* pBin, int nBin)
    {
        strcpy(m_szPwd, pszPwd);
        Pack(szKey, pBin, nBin);
    }

    bool MixPool::Pack(const char* pszKey, const char* pszVal)
    {
        Put(pszKey, (char*)pszVal);
        MemJson::Val x = Get(pszKey);
        CrypUtil::Encrypt2((void*)x.v, (void*)x.v, x.n, m_szPwd);
        return true;
    }

    bool MixPool::Pack(const char* pszKey, void* pData, uint32_t nData)
    {
        Put(pszKey, pData, nData);
        MemJson::Val x = Get(pszKey);
        CrypUtil::Encrypt2((void*)x.v, (void*)x.v, x.n, m_szPwd);
        return true;
    }

    const void* MixPool::Lock(const char* pszKey, uint32_t* pnData)
    {
        MemJson::Val x = Get(pszKey);
        if (!x.IsValid()) { return nullptr; }

        if (pnData) { *pnData = x.n; }

        uint32_t uHash = StrUtil::CalcHash(pszKey, false, false);
        if (setLocked.count(uHash) == 1)
        {
            return (void*)x.v;
        }
        CrypUtil::Decrypt2((void*)x.v, (void*)x.v, x.n, m_szPwd);
        setLocked.insert(uHash);

        return (void*)x.v;
    }

    void MixPool::Unlock(const char* pszKey)
    {
        MemJson::Val x = Get(pszKey);
        if (!x.IsValid()) { return; }
        
        uint32_t uHash = StrUtil::CalcHash(pszKey, false, false);
        if (setLocked.count(uHash) == 1)
        {
            CrypUtil::Encrypt2((void*)x.v, (void*)x.v, x.n, m_szPwd);
            setLocked.erase(uHash);
        }
    }

    // 仅返回值 == *pnData != 0 表示解包成功
    uint32_t MixPool::Unpack(const char* pszKey, void* pData, uint32_t* pnData) const
    {
        MemJson::Val x = Get(pszKey);
        if (!pData || x.n > *pnData)
        {
            *pnData = 0;
            return x.n;
        }
        CrypUtil::Decrypt2((void*)x.v, pData, x.n, m_szPwd);
        *pnData = x.n;
        return x.n;
    }

    void MixPool::Clear() { return MemJson::Clear(); };
    void* MixPool::Mem() const { return MemJson::Mem(); }
    uint32_t MixPool::Len() const { return MemJson::Len(); }
    uint32_t MixPool::Cnt() const { return MemJson::Cnt(); }
    bool MixPool::IsValid() { return MemJson::IsValid(); }
    bool MixPool::Build(void* pMem, uint32_t nLen) { return MemJson::Build(pMem, nLen); }
}
